package com.xxh.dasongapp.security.config;

import com.xxh.dasongapp.security.config.filter.JWTAuthenticationFilter;
import com.xxh.dasongapp.security.config.handler.UserAuthAccessDeniedHandler;
import com.xxh.dasongapp.security.config.handler.UserAuthenticationEntryPointHandler;
import com.xxh.dasongapp.security.provider.WXProvider;
import com.xxh.dasongapp.security.service.UserOpenIdDetailsService;
import com.xxh.dasongapp.security.service.impl.UserNameDetailServiceImpl;

import com.xxh.dasongapp.security.service.impl.UserOpenIdDetailServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.Arrays;

@Configuration
@EnableWebSecurity
//开启注解配置权限
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig  extends WebSecurityConfigurerAdapter {


    @Autowired
    //用户名密码登录
    private UserNameDetailServiceImpl userNameDetailServiceImpl;


    @Autowired
    //openid登录
    private UserOpenIdDetailServiceImpl userOpenIdDetailServiceImpl;

    @Autowired
    //token过滤器
    private JWTAuthenticationFilter jwtAuthenticationFilter;

    @Autowired
    //无权限处理器
    private UserAuthAccessDeniedHandler userAuthAccessDeniedHandler;

    @Autowired
    //未登录处理器
    private UserAuthenticationEntryPointHandler userAuthenticationEntryPointHandler;



    /**
     * 创建密码加密方式BCryptPasswordEncoder注入容器中
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }



    /**
     * 定义认证管理器
     * @return
     * @throws Exception
     */
    @Override
    @Bean(name="myAuthenticationManager")
    public AuthenticationManager authenticationManagerBean() throws Exception {
        ProviderManager authenticationManager = new ProviderManager(Arrays.asList(daoAuthenticationProvider(),getWXProvider()));
        //不擦除认证密码，擦除会导致TokenBasedRememberMeServices因为找不到Credentials再调用UserDetailsService而抛出UsernameNotFoundException
        authenticationManager.setEraseCredentialsAfterAuthentication(false);
        return authenticationManager;
    }



    /**
     * 配置provider(DaoAuthenticationProvider) 用户名密码的一套
     * @return
     */
    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider(){
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        daoAuthenticationProvider.setUserDetailsService(userNameDetailServiceImpl);
        return daoAuthenticationProvider;
    }


    /**
     * 配置provider(WXProvider) 微信的一套（根据openid直接登入系统）
     * @return
     */
    @Bean
    public WXProvider getWXProvider(){
        WXProvider wxProvider = new WXProvider();
        wxProvider.setUserOpenIdDetailsService(userOpenIdDetailServiceImpl);
        return wxProvider;
    }

    public void configure(WebSecurity web) throws Exception {
        // 忽略URL
        web.ignoring().antMatchers("/img/**",
                "/static/img/**",
                "/druid/**"
               );
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //关闭csrf防护
        http.csrf().disable();
        //基于token，不需要session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        //请求认证
        http.authorizeRequests()
                .antMatchers("/notice/page/**",
                        "/notice/getById/**",
                        "/carousel/page/**",
                        "/carousel/getById/**",
                        "/website/page/**",
                        "/website/getById/**",
                        "/resource/page/**",
                        "/resource/getById/**",
                        "/css/**",
                        "/druid/**",
                        "/static/img/**",
                        "/img/**",
                        "/temp/**",
                        "/login/**",
                        "/js/**",
                        "/index.html",
                        "**/doc.html",
                        "/doc.html",
                        "/doc.html/**",
                        "/webjars/**",
                        "/v2/**",
                        "/swagger-resources",
                        "/swagger-resources/**",
                        "/swagger-ui.html",
                        "/swagger-ui.html/**",
                        "/favicon.ioc").permitAll()
                //全部除了上面的全部需要认证
                .anyRequest().authenticated();

        http
                //添加token认证的过滤器到security的过滤链前
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        http
                //配置认证失败处理器和授权失败处理器
                .exceptionHandling()
                .authenticationEntryPoint(userAuthenticationEntryPointHandler)
                .accessDeniedHandler(userAuthAccessDeniedHandler);

    }


}
